package com.share.filter;

import cn.hutool.jwt.JWTUtil;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.share.constant.Result;
import com.share.holder.ContextHolder;
import com.share.holder.UUIDHolder;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.TimeUnit;

import static com.share.constant.DefaultConstant.*;
import static com.share.constant.StatusCode.*;

@Component
@Slf4j
public class JWTFilter extends OncePerRequestFilter {

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    ObjectMapper objectMapper ;

    private static final List<String> WHITE_LIST = Arrays.asList( "/user/register", "/user/logout",
            "/user/forgetPassword", "/user/getPhoneCaptcha",
            "/user/login/phone","/user/getCaptcha", "/user/checkUserName","/swagger-ui/",
            "/v3/api-docs", "/swagger-resources/", "/webjars/","/user/login/username"
    );

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
            throws ServletException, IOException {

        String url = request.getRequestURI();

        log.info("请求路径：{}", url);
        String uuid = request.getHeader(X_CAPTCHA_UUID);
        if(uuid!=null){
            UUIDHolder.set(uuid);
        }

        // 放行白名单路径
        if (WHITE_LIST.contains(url)) {
            filterChain.doFilter(request, response);
            return;
        }


        // 获取请求头中的令牌
        String token = request.getHeader(TOKEN_KEY);
        System.out.println("token:"+token);

        try {
            if (token == null || "".equals(token) || !JWTUtil.verify(token, JWT_KEY.getBytes())) {
                // 令牌无效
                sendUnauthorizedResponse(response, Result.fail(TOKEN_ERROR.getCode(), TOKEN_ERROR.getMessage()));
                return;
            }

            // 从token中获取用户id
            Long userId = Long.parseLong(JWTUtil.parseToken(token).getPayload(USERNAME_ID).toString());

            // 从Redis中获取token进行比较
            String redisToken = (String)redisTemplate.opsForValue().get(USER_LOGIN_KEY + userId);
            if (redisToken == null || !redisToken.equals(token)) {
                // 表示异地登录了
                sendUnauthorizedResponse(response, Result.fail(LOGIN_OUT_MESSAGE.getCode(), LOGIN_OUT_MESSAGE.getMessage()));
                return;
            }

            // 刷新令牌有效期，并将用户id放入threadlocal中
            redisTemplate.expire(USER_LOGIN_KEY + userId, TOKEN_TIME, TimeUnit.HOURS);
            System.out.println("userId:"+userId);
            ContextHolder.set(userId);


            // 继续过滤器链
            filterChain.doFilter(request, response);

        } catch (Exception e) {
            log.error("Error processing JWT filter", e);
            sendUnauthorizedResponse(response, Result.fail(INTERNAL_ERROR.getCode(), INTERNAL_ERROR.getMessage()));
        } finally {
            ContextHolder.clear();
        }
    }

    private void sendUnauthorizedResponse(HttpServletResponse response, Result result) throws IOException {
        response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
        response.setContentType("application/json;charset=UTF-8");
        response.getWriter().write(objectMapper.writeValueAsString(result));
    }
}
